{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Storage investment optimisation with oemof\n",
    "\n",
    "### General description:\n",
    "\n",
    "The jupyter notebook gives an example of storage capacity optimization.\n",
    "\n",
    "### Installation requirements:\n",
    "\n",
    "This example requires oemof 0.1.4 and jupyter. Install by:\n",
    "\n",
    "    pip install oemof==0.1.4 jupyter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import logging\n",
    "from oemof.tools import logger\n",
    "logger.define_logging()\n",
    "\n",
    "logging.info('The program started')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# INSTANTIATE ENERGY SYSTEM\n",
    "\n",
    "import pandas as pd\n",
    "from oemof import solph\n",
    "\n",
    "date_time_index = pd.date_range('1/1/2017', periods=8760,\n",
    "                               freq='H')\n",
    "\n",
    "energysystem = solph.EnergySystem(timeindex=date_time_index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(energysystem)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "# Import wind, PV and demand data\n",
    "data = pd.read_csv('data/example_data.csv', sep=',')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define cost parameter\n",
    "\n",
    "from oemof.tools import economics\n",
    "\n",
    "price_gas = 0.04\n",
    "\n",
    "epc_wind = economics.annuity(capex=1000, n=20, wacc=0.05)  # equivalent periodical costs\n",
    "\n",
    "epc_pv = economics.annuity(capex=1000, n=20, wacc=0.05)\n",
    "\n",
    "epc_storage = economics.annuity(capex=1000, n=10, wacc=0.05)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# POPULATE ENERGY SYSTEM\n",
    "\n",
    "from oemof import solph\n",
    "\n",
    "# Create busses\n",
    "bgas = solph.Bus(label='natural_gas')\n",
    "\n",
    "bel = solph.Bus(label='electricity')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create sources\n",
    "\n",
    "solph.Source(label='gas',\n",
    "             outputs={bgas: solph.Flow(variable_costs=price_gas)})\n",
    "\n",
    "solph.Source(label='wind',\n",
    "             outputs={bel: solph.Flow(\n",
    "                 actual_value=data['wind'],\n",
    "                 fixed=True,\n",
    "                 fixed_costs=20,\n",
    "                 investment=solph.Investment(ep_costs=epc_wind))})\n",
    "\n",
    "solph.Source(label='pv',\n",
    "             outputs={bel: solph.Flow(\n",
    "                 actual_value=data['pv'],\n",
    "                 fixed=True,\n",
    "                 fixed_costs=20,\n",
    "                 investment=solph.Investment(ep_costs=epc_pv))})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create sinks\n",
    "\n",
    "solph.Sink(label='demand',\n",
    "           inputs={bel: solph.Flow(\n",
    "               actual_value=data['demand_el'],\n",
    "               fixed=True,\n",
    "               nominal_value=1)})\n",
    "\n",
    "solph.Sink(label='excess_bel',\n",
    "           inputs={bel: solph.Flow()})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create transformer\n",
    "\n",
    "solph.LinearTransformer(label='pp_gas',\n",
    "                        inputs={bgas: solph.Flow()},\n",
    "                        outputs={bel: solph.Flow(\n",
    "                            nominal_value=10e10,\n",
    "                            variable_costs=0)},\n",
    "                        conversion_factors={bel: 0.58})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create storage\n",
    "\n",
    "solph.Storage(label='storage',\n",
    "              inputs={bel: solph.Flow(variable_costs=1)},\n",
    "              outputs={bel: solph.Flow()},\n",
    "              capacity_loss=0,\n",
    "              initial_capacity=0,\n",
    "              nominal_input_capacity_ratio=1/6,\n",
    "              nominal_output_capacity_ratio=1/6,\n",
    "              inflow_conversion_factor=1,\n",
    "              outflow_conversion_factor=0.8,\n",
    "              fixed_costs=35,\n",
    "              investment=solph.Investment(ep_costs=epc_storage))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# COMPUTE RESULTS\n",
    "\n",
    "om = solph.OperationalModel(energysystem)\n",
    "\n",
    "om.solve(solver='cbc', solve_kwargs={'tee': True})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# filename = os.path.join(\n",
    "#             helpers.extend_basic_path('lp_files'), 'storage_invest.lp')\n",
    "# logging.info('Store lp-file in {0}.'.format(filename))\n",
    "# om.write(filename, io_options={'symbolic_solver_labels': True})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# PROCESS RESULTS\n",
    "\n",
    "from oemof import outputlib\n",
    "\n",
    "storage = energysystem.groups['storage']\n",
    "wind_inst = energysystem.groups['wind']\n",
    "pv_inst = energysystem.groups['pv']\n",
    "myresults = outputlib.DataFramePlot(energy_system=energysystem)\n",
    "\n",
    "pp_gas = myresults.slice_by(obj_label='pp_gas', type='to_bus',\n",
    "                            date_from='2017-01-01 00:00:00',\n",
    "                            date_to='2017-12-31 23:00:00')\n",
    "\n",
    "demand = myresults.slice_by(obj_label='demand',\n",
    "                            date_from='2017-01-01 00:00:00',\n",
    "                            date_to='2017-12-31 23:00:00')\n",
    "\n",
    "import pprint as pp\n",
    "pp.pprint({\n",
    "    'wind_inst_MW': energysystem.results[wind_inst][bel].invest/1000,\n",
    "    'pv_inst_MW': energysystem.results[pv_inst][bel].invest/1000,\n",
    "    'storage_cap_GWh': energysystem.results[storage][storage].invest/1e6,\n",
    "    'res_share': 1 - pp_gas.sum()/demand.sum(),\n",
    "    'objective': energysystem.results.objective\n",
    "    })"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "cdict = {'wind': '#5b5bae',\n",
    "         'pv': '#ffde32',\n",
    "         'storage': '#42c77a',\n",
    "         'pp_gas': '#636f6b',\n",
    "         'demand': '#ce4aff',\n",
    "         'excess_bel': '#555555'}\n",
    "\n",
    "myplot = outputlib.DataFramePlot(energy_system=energysystem)\n",
    "# Plotting the balance around the electricity plot for one week using a\n",
    "# combined stacked plot\n",
    "fig = plt.figure(figsize=(24, 14))\n",
    "plt.rc('legend', **{'fontsize': 19})\n",
    "plt.rcParams.update({'font.size': 19})\n",
    "plt.style.use('grayscale')\n",
    "\n",
    "handles, labels = myplot.io_plot(\n",
    "    bus_label='electricity', cdict=cdict,\n",
    "    barorder=['pv', 'wind', 'pp_gas', 'storage'],\n",
    "    lineorder=['demand', 'storage', 'excess_bel'],\n",
    "    line_kwa={'linewidth': 4},\n",
    "    ax=fig.add_subplot(1, 1, 1),\n",
    "    date_from=\"2017-06-01 00:00:00\",\n",
    "    date_to=\"2017-06-08 00:00:00\",\n",
    "    )\n",
    "myplot.ax.set_ylabel('Power in kW')\n",
    "myplot.ax.set_xlabel('Date')\n",
    "myplot.ax.set_title(\"Electricity bus\")\n",
    "myplot.set_datetime_ticks(tick_distance=24, date_format='%d-%m-%Y')\n",
    "myplot.outside_legend(handles=handles, labels=labels)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
